package com.foreverwin.mes.so.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.foreverwin.mes.common.model.KeyLock;
import com.foreverwin.mes.common.service.KeyLockService;
import com.foreverwin.mes.core.base.FrontPage;
import com.foreverwin.mes.core.exception.BusinessException;
import com.foreverwin.mes.core.utils.I18nUtil;
import com.foreverwin.mes.core.utils.StringUtils;
import com.foreverwin.mes.so.dto.CycleTimeDeleteReq;
import com.foreverwin.mes.so.dto.InactiveTimeDto;
import com.foreverwin.mes.so.mapper.CycleTimeConfigMapper;
import com.foreverwin.mes.so.model.CycleTimeConfig;
import com.foreverwin.mes.so.model.CycleTimeConfigView;
import com.foreverwin.mes.so.service.CycleTimeConfigService;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Syngna
 * @since 2020-01-14
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class CycleTimeConfigServiceImpl extends ServiceImpl<CycleTimeConfigMapper, CycleTimeConfig> implements CycleTimeConfigService {


    @Autowired
    private CycleTimeConfigMapper cycleTimeConfigMapper;

    @Autowired
    private KeyLockService keyLockService;

    @Override
    public Page<CycleTimeConfig> selectPage(FrontPage<CycleTimeConfig> frontPage, CycleTimeConfig cycleTimeConfig) {
        EntityWrapper<CycleTimeConfig> queryWrapper = new EntityWrapper<>();
        queryWrapper.setEntity(cycleTimeConfig);
        return super.selectPage(frontPage.getPagePlus(), queryWrapper);
    }

    @Override
    public List<CycleTimeConfig> selectList(CycleTimeConfig cycleTimeConfig) {
        EntityWrapper<CycleTimeConfig> queryWrapper = new EntityWrapper<>();
        queryWrapper.setEntity(cycleTimeConfig);
        return super.selectList(queryWrapper);
    }

    @Override
    public List<CycleTimeConfigView> selectKeySelectiveList(CycleTimeConfigView cycleTimeConfigView) {
        Locale locale = LocaleContextHolder.getLocale();
        cycleTimeConfigView.setLocale(locale.getLanguage());
        return cycleTimeConfigMapper.selectKeySelective(cycleTimeConfigView);
    }

    /**
     * <p>
     * 插入一条记录（选择字段，策略插入，防止重复插入）
     * </p>
     *
     * @param cycleTimeConfig 实体对象
     * @return boolean
     */
    @Override
    public boolean insert(CycleTimeConfig cycleTimeConfig) {
        cycleTimeConfig.setHandle(StringUtils.createQUID());
        KeyLock keyLock = new KeyLock();
        keyLock.setHandle(cycleTimeConfig.getKey());
        keyLock.setObjRef(cycleTimeConfig.getHandle());
        keyLockService.insert(keyLock);
        return super.insert(cycleTimeConfig);
    }

    @Override
    public boolean insertBatch(List<CycleTimeConfig> cycleTimeConfigs) {
        return insertBatch(cycleTimeConfigs, 30);
    }

    @Override
    public boolean insertBatch(List<CycleTimeConfig> cycleTimeConfigs, int batchSize) {
        List<KeyLock> keyLocks = new ArrayList<KeyLock>();
        for( CycleTimeConfig cycleTimeConfig : cycleTimeConfigs ) {

            KeyLock keyLock = new KeyLock();
            keyLock.setHandle(cycleTimeConfig.getKey());
            keyLock.setObjRef(cycleTimeConfig.getHandle());
            keyLocks.add(keyLock);

            cycleTimeConfig.setHandle(StringUtils.createQUID());
        }
        keyLockService.insertBatch(keyLocks);
        return super.insertBatch(cycleTimeConfigs, batchSize);
    }

    @Override
    public boolean updateById(CycleTimeConfig cycleTimeConfig) {
        if( super.updateById(cycleTimeConfig) ) {
            return true;
        } else {
            throw new RuntimeException(I18nUtil.getI18nText("common.updateByOther.error"));
        }
    }

    @Override
    public void deleteById(CycleTimeDeleteReq cycleTimeDeleteReq) {
        deleteBatchById(Arrays.asList(cycleTimeDeleteReq));
    }

    /**
     * 批次删除
     * @param cycleTimeDeleteReqs
     */
    @Override
    public void deleteBatchById(List<CycleTimeDeleteReq> cycleTimeDeleteReqs) {
        List<String> deleteLockKeys = new ArrayList<String>();
        for( CycleTimeDeleteReq req : cycleTimeDeleteReqs ) {
            if( req.getModifiedDateTime() == null ) {
                throw new RuntimeException(I18nUtil.getI18nText("common.noneLockVersion.error"));
            }
            if( StringUtils.isBlank(req.getUser()) ) {
                throw new RuntimeException(I18nUtil.getI18nText("common.noneUser.error"));
            }
            deleteLockKeys.add(req.getHandle());
            CycleTimeConfig cycleTimeConfig = new CycleTimeConfig();
            cycleTimeConfig.setHandle(req.getHandle());
            cycleTimeConfig.setUpdater(req.getUser());
            cycleTimeConfig.setModifiedDateTime(req.getModifiedDateTime());
            cycleTimeConfig.setStatus("D");
            updateById(cycleTimeConfig);
        }
        keyLockService.batchDeleteByRefKey(deleteLockKeys);
    }

    /**
     * 批次删除，废弃
     * 添加乐观锁插件后，批次更新修改不到已经被其他用户更新过的数据，也不会报错
     * @param cycleTimeDeleteReqs
     */
    @Deprecated
    public void deleteBatch(List<CycleTimeDeleteReq> cycleTimeDeleteReqs) {
        List<CycleTimeConfig> cycleTimeConfigList = new ArrayList<CycleTimeConfig>();
        for( CycleTimeDeleteReq req : cycleTimeDeleteReqs ) {
            if( req.getModifiedDateTime() == null ) {
                throw new RuntimeException(I18nUtil.getI18nText("common.noneLockVersion.error"));
            }
            if( StringUtils.isBlank(req.getUser()) ) {
                throw new RuntimeException(I18nUtil.getI18nText("common.noneUser.error"));
            }
            CycleTimeConfig cycleTimeConfig = new CycleTimeConfig();
            cycleTimeConfig.setHandle(req.getHandle());
            cycleTimeConfig.setUpdater(req.getUser());
            cycleTimeConfig.setModifiedDateTime(req.getModifiedDateTime());
            cycleTimeConfig.setStatus("D");
            cycleTimeConfigList.add(cycleTimeConfig);
        }
        if(!updateBatchById(cycleTimeConfigList)) {
            throw new RuntimeException(I18nUtil.getI18nText("common.updateByOther.error"));
        }
    }

    @Override
    public List<CycleTimeConfig> getCycleTimeByResourceAndItem(String site, String resourceBo, String itemBo) {
        String resource = StringUtils.trimHandle(resourceBo);
        return this.selectList(new EntityWrapper<CycleTimeConfig>()
                .eq(CycleTimeConfig.SITE, site)
                .eq(CycleTimeConfig.RESRCE, resource)
                .eq(CycleTimeConfig.ITEM_BO, itemBo)
                .eq(CycleTimeConfig.STATUS, "Y"));
    }

    /**
     * 根据资源handle,物料handle获取CT秒数
     * @param site
     * @param resourceBo
     * @param itemBo
     * @return
     * @throws BusinessException
     */
    @Transactional(propagation= Propagation.NOT_SUPPORTED)
    @Override
    public BigDecimal getCycleTime(String site, String resourceBo, String itemBo) throws BusinessException {
        List<CycleTimeConfig> cycleTimeConfigList = getCycleTimeByResourceAndItem(site, resourceBo, itemBo);
        BigDecimal cycleTime;
        if (cycleTimeConfigList == null || cycleTimeConfigList.size() == 0) {
            return null;
        } else if (cycleTimeConfigList.size() > 1) {
            throw BusinessException.build("物料" + itemBo + "在设备" + StringUtils.trimHandle(resourceBo) + "上CT时间重复设定");
        } else {
            cycleTime = new BigDecimal(cycleTimeConfigList.get(0).getCycleTime());
        }
        return cycleTime;
    }

    @Override
    public List<CycleTimeConfig> selectByItemAndOperation(String site, String itemBo, String operation) {
        return cycleTimeConfigMapper.selectByItemAndOperation(site, itemBo, operation);
    }

    @Override
    public List<InactiveTimeDto> selectInactiveTime(String site, String item) {
        return cycleTimeConfigMapper.selectInactiveTime(site, item);
    }
}